home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Memory / MemDebg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  18.7 KB  |  708 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemDebg.cpp
  3.  
  4.     Contains:    Memory management debug routine implementations
  5.  
  6.     Owned by:    Jens Alfke
  7.     Owned by:    Jens Alfke, Vincent Lo, Nick Pilch, Michael Burbidge
  8.  
  9.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.          <5>    02.10.1996    NP        1386083: Changed name of debugging routines
  14.          <4>     9/30/96    TJ        Fixed non-debug.
  15.          <3>    27.09.1996    NP        1386083: New routines MMBlockAllocations
  16.                                     and MMUnslockAllocations
  17.          <2>     9/13/96    jpa        1371387: Speed optimizations.
  18.         <23>     10/3/95    TJ        Opps, I had left some code in that had been
  19.                                     if defed out.
  20.         <22>     10/3/95    TJ        Changes done by RefBall Team
  21.         <21>      8/8/95    TJ        Declared FindLeaksProc extern C
  22.         <20>      8/7/95    TJ        Typecast &InitLeaksProc to
  23.                                     (MMBlockInfoProc) for the MMWalkHeap call
  24.                                     so it will compile with SCpp.
  25.         <19>      8/4/95    DM        Leak checking [1267956]
  26.         <18>     6/21/95    JBS        turn off heap validation for ∂SOM data xfer
  27.         <17>      6/7/95    jpa        Changed old (pre-SLIM) SOM includes to
  28.                                     som.xh [1256901]
  29.         <16>      5/4/95    jpa        Added MMFindBlockContaining [1246077]
  30.         <15>    12/20/94    jpa        Add stub routines in non-debug config so
  31.                                     library will build. [1188344]
  32.         <14>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  33.         <13>    10/24/94    jpa        Constness [1194286]
  34.         <12>     9/29/94    RA        1189812: Mods for 68K build.
  35.         <11>     9/20/94    VL        jpa: Fixed infinite recursion in heap
  36.                                     validation.
  37.         <10>     9/14/94    jpa        Eliminated dependencies on rest of OpenDoc.
  38.                                     OD-->MM. [1186692]
  39.          <9>      9/9/94    jpa        Made ODValidatePtr more robust.
  40.          <8>     8/19/94    NP        1181622: Ownership fix.
  41.          <7>     8/17/94    jpa        Added ODWalkHeap, greatly improved
  42.                                     ODValidateObject, and added debugging
  43.                                     checks using the SOM-block flag. [1179567]
  44.          <6>      8/8/94    jpa        Added ODGetHeapInfo. [1179567]
  45.          <5>      8/2/94    jpa        Plenty more fixes to validation.
  46.          <4>     7/26/94    jpa        Got validation stuff to work again.
  47.          <3>     6/18/94    MB        Include MemDebgP.h
  48.          <2>     6/10/94    MB        Make it build
  49.          <1>      6/9/94    MB        first checked in
  50.          <3>     5/27/94    jpa        New exception support [1165267]
  51.          <2>     5/27/94    MB        #1162181: Fixed MMM integration bug
  52.          <1>     5/27/94    MB        first checked in
  53.     To Do:
  54.     
  55.     In Progress:
  56.         
  57. */
  58.  
  59. #ifndef _MEMCNFIG_
  60. #include "MemCnfig.h"
  61. #endif
  62.  
  63. #ifndef _MEMDEBG_
  64. #include "MemDebg.h"
  65. #endif
  66.  
  67.  
  68. #if MM_DEBUG
  69.  
  70.  
  71. #ifndef _MEMMGRPV_
  72. #include "MemMgrPv.h"
  73. #endif
  74.  
  75. #ifndef _MEMHOOKS_
  76. #include "MemHooks.h"
  77. #endif
  78.  
  79. #include <string.h>
  80.  
  81. #ifndef __SOM__
  82. #include <som.xh>
  83. #endif
  84.  
  85. #include <SOMObj.xh>
  86.  
  87. #ifndef _CRAWL_
  88. #include "Crawl.h"
  89. #endif
  90.  
  91. #ifndef __LOWMEM__
  92. #include <LowMem.h>
  93. #endif
  94.  
  95.  
  96. //==============================================================================
  97. // Global variable definitions
  98. //==============================================================================
  99.  
  100. mmboolean gValidate = 0;
  101. mmboolean gHeapChecking = 0;
  102.  
  103.  
  104. //==============================================================================
  105. // Function definitions
  106. //==============================================================================
  107.  
  108.  
  109. //------------------------------------------------------------------------------
  110. // DoesHeapExist
  111. //------------------------------------------------------------------------------
  112.  
  113. MMBoolean MMDoesHeapExist( MemHeap *heap )
  114. {
  115.     if( ((MemoryHeap*)heap)->GetLocation()==kMMSysMemory )
  116.         return kMMTrue;        // A system heap might have been allocated by another process.
  117.         
  118.     for( MemoryHeap *h = MemoryHeap::GetFirstHeap(); h; h = h->GetNextHeap() )
  119.         if( h == (MemoryHeap*)heap )
  120.             return kMMTrue;
  121.     return kMMFalse;
  122. }
  123.  
  124. //------------------------------------------------------------------------------
  125. // MMBeginMemValidation
  126. //------------------------------------------------------------------------------
  127.  
  128. void
  129. MMBeginMemValidation( )
  130. {
  131.     MMValidateAllHeaps();
  132.     if( gValidate==0 )
  133.         for( MemoryHeap *h = MemoryHeap::GetFirstHeap(); h; h = h->GetNextHeap() ) {
  134.             h->SetZapOnAllocate(kMMTrue);
  135.             h->SetZapOnFree(kMMTrue);
  136.             h->SetAutoValidation(kMMTrue);
  137.         }
  138.     gValidate++;
  139. }
  140.  
  141. //------------------------------------------------------------------------------
  142. // MMEndMemValidation
  143. //------------------------------------------------------------------------------
  144.  
  145. void
  146. MMEndMemValidation( )
  147. {
  148.     if( gValidate<=0 ) {
  149.         MM_WARN("Improper nesting of memory-validation calls");
  150.         return;
  151.     }
  152.     
  153.     MMValidateAllHeaps();
  154.     gValidate--;
  155.     if (gValidate==0)
  156.         for( MemoryHeap *h = MemoryHeap::GetFirstHeap(); h; h = h->GetNextHeap() ) {
  157.             h->SetZapOnAllocate(kMMFalse);
  158.             h->SetZapOnFree(kMMFalse);
  159.             h->SetAutoValidation(kMMFalse);
  160.         }
  161. }
  162.  
  163. //------------------------------------------------------------------------------
  164. // MMBeginHeapChecking
  165. //------------------------------------------------------------------------------
  166.  
  167. void
  168. MMBeginHeapChecking( )
  169. {
  170.     gHeapChecking++;
  171.     MMBeginMemValidation();
  172. }
  173.  
  174. //------------------------------------------------------------------------------
  175. // MMEndHeapChecking
  176. //------------------------------------------------------------------------------
  177.  
  178. void
  179. MMEndHeapChecking( )
  180. {
  181.     if( gHeapChecking<=0 ) {
  182.         MM_WARN("Improper nesting of heap-checking calls");
  183.         return;
  184.     }
  185.     
  186.     gHeapChecking--;
  187.     MMEndMemValidation();
  188. }
  189.  
  190. //------------------------------------------------------------------------------
  191. // MMValidateHeap
  192. //------------------------------------------------------------------------------
  193.  
  194. static MMBoolean
  195. HeapCheckProc( const void *blk, unsigned long /*size*/, MMBoolean isObject, void *refCon )
  196. {
  197.     if( isObject ) {
  198.         (*(MMULong*)refCon) ++;                            // Increment object count
  199.         MMValidateObject((SOMObject*)blk);
  200.     }
  201.     return true;
  202. }
  203.  
  204.  
  205. MMBoolean
  206. MMValidateHeap( MemHeap *heapID, const void* ptr )
  207. {
  208.     if (!heapID )
  209.         heapID = MMGetDefaultHeap();
  210.  
  211.     MM_ASSERT(heapID);
  212.     
  213. #if 0
  214.     if (!MMDoesHeapExist(heapID)) {
  215.         if( ptr )
  216.             MM_WARN("%p's heap at %p is unknown", ptr,heapID);
  217.         else
  218.             MM_WARN("%p is not a known heap", heapID);
  219.         return kMMFalse;
  220.     }
  221. #endif
  222.  
  223.     MMULong objects = 0;
  224.     ((MemoryHeap*)heapID)->Check(&HeapCheckProc,&objects);
  225.     
  226.     return kMMTrue;
  227. }
  228.  
  229.  
  230. //------------------------------------------------------------------------------
  231. // MMValidateAllHeaps
  232. //------------------------------------------------------------------------------
  233.  
  234. MMBoolean
  235. MMValidateAllHeaps( )
  236. {
  237.     MMBoolean result = kMMTrue;
  238.     for( MemoryHeap *h = MemoryHeap::GetFirstHeap(); h; h = h->GetNextHeap() )
  239.         if( !MMValidateHeap((MemHeap*)h) )
  240.             result = kMMFalse;
  241.     return result;
  242. }
  243.  
  244.  
  245. //------------------------------------------------------------------------------
  246. // MMValidatePtr
  247. //------------------------------------------------------------------------------
  248.  
  249. MMBoolean
  250. MMValidatePtr( const void* p, MMBoolean validateHeap, const char *operation )
  251. {
  252.     // If we could be sure that p were in the app zone, we could be more
  253.     // stringent. But it might be in the System heap or in temp-mem.
  254.     
  255.     const char *err = BasicValidatePtr(p);
  256.     if( !err ) {
  257.         BestFitHeap *heap = (BestFitHeap*) gDefaultHeap->GetBlockHeap(p);
  258.         
  259. #if 0
  260.         if (!MMDoesHeapExist((MemHeap*)heap))
  261.             if( operation )
  262.                 MM_WARN("%s(%p): block's heap %p is unknown", operation,p,heap);
  263.             else
  264.                 MM_WARN("%p's heap %p is unknown", p,heap);
  265. #endif
  266.         
  267.         if( !heap->IsValidBlock(p) ) {
  268.             err = "is invalid";
  269.             if( somIsObj((void*)p) ) {
  270.                 MM_WARN("Invalid block %p is an object of class %s",
  271.                             p, ((SOMObject*)p)->somGetClassName() );
  272.             }
  273.         } else if( validateHeap && !MMValidateHeap((MemHeap*)heap,p) )
  274.             return kMMFalse;    // ODValidateHeap already warns the user
  275.         else
  276.             return kMMTrue;
  277.     }
  278.     
  279.     if( operation )
  280.         MM_WARN("%s(%p): ptr %s!",operation,p,err);
  281.     else
  282.         MM_WARN("Pointer %p %s!",p,err);
  283.     return kMMFalse;
  284. }
  285.  
  286.  
  287. //------------------------------------------------------------------------------
  288. // MMValidateObject
  289. //------------------------------------------------------------------------------
  290.  
  291. static mmboolean
  292. BasicIsObject( const void *block )
  293. {
  294.     // This is like MMIsObject but does not do any heap checking, which would
  295.     // be fatal if MMValidateObject were already being called during a heap-check!
  296.     
  297.     MemoryHeap *heap = gDefaultHeap->GetBlockHeap(block);
  298.     return heap ?heap->BlockIsObject(block) :kMMFalse;
  299. }
  300.  
  301. MMBoolean
  302. MMValidateObject( const SOMObject *o )
  303. {
  304.     // I mustn't check the heap, since I am called during heap checking!!
  305.     if( !MMValidatePtr(o,kMMFalse,"MMValidateObject") )
  306.         return kMMFalse;
  307.     
  308.     const char *err;
  309.     if( !BasicIsObject(o) )
  310.         err = "is not marked as an object in the heap";
  311.     else if( !gHaveSOM || !somIsObj((SOMObject*)o) )
  312.         err = "is not a SOM object";
  313.     else
  314.         return kMMTrue;
  315.     
  316.     MM_WARN("Object %p %s!", o, err);
  317.     return kMMFalse;
  318. }
  319.  
  320.  
  321. #if MM_INSTRUMENT
  322. const long kSizeSurveySize = 100;
  323.  
  324. struct SurveyData {
  325.     long *sizes;
  326.     unsigned long blocks;
  327.     unsigned long sizeTotal;
  328.     unsigned long realTotal;
  329.     BestFitHeap *heap;
  330. };
  331.  
  332. static MMBoolean
  333. HeapSurveyProc( const void *blk, unsigned long size, MMBoolean isObject, void *refCon )
  334. {
  335.     SurveyData &survey = *(SurveyData*)refCon;
  336.     survey.blocks++;
  337.     survey.sizeTotal += size;
  338.     size = survey.heap->GetBlockRealSize(blk);
  339.     survey.realTotal += size;
  340.  
  341.     size = (size+3) >> 2;
  342.     if( size < kSizeSurveySize )
  343.         survey.sizes[size]++;
  344.     else
  345.         survey.sizes[kSizeSurveySize]++;
  346.     return true;
  347. }
  348. #endif
  349.  
  350. //------------------------------------------------------------------------------
  351. // MMGetHeapInfo
  352. //------------------------------------------------------------------------------
  353.  
  354. void
  355. MMGetHeapInfo( MemHeap *heapID,
  356.                 const char* *name, size_t *allocated, size_t *free,
  357.                 size_t *nBlocks, size_t *nObjects )
  358. {
  359.     MemoryHeap *heap = (MemoryHeap*)( heapID ?heapID :MMGetDefaultHeap() );
  360.     
  361.     ((BestFitHeap*)heap)->Coalesce();
  362.     
  363.     if( name )        *name = heap->GetDescription();
  364.     if( allocated )    *allocated = heap->BytesAllocated();
  365.     if( free )        *free = heap->BytesFree();
  366.     if( nBlocks )    *nBlocks = heap->NumberAllocatedBlocks();
  367.     
  368.     if( nObjects ) {
  369.         *nObjects = 0;
  370.         heap->Check(&HeapCheckProc,&*nObjects);
  371.     }
  372.  
  373. #if MM_INSTRUMENT
  374.     long sizes[kSizeSurveySize+1];
  375.     for( int i=kSizeSurveySize; i>=0; i-- )
  376.         sizes[i] = 0;
  377.     SurveyData survey = {sizes,0,0,0,(BestFitHeap*)heap};
  378.     ((BestFitHeap*)heap)->Coalesce();
  379.     heap->Check(&HeapSurveyProc,&survey);
  380. //    MM_WARN("Total = %ld/%ld, %ld blocks. Check the sizes now: %p",
  381. //        survey.sizeTotal,survey.realTotal,survey.blocks,sizes);
  382.     somPrintf("•••RESULTS•••\n%ld blocks. Logical size=%ld, plus %ld bytes internal fragmentation"
  383.                 " and %ld bytes of headers.\n",
  384.                 survey.blocks,survey.realTotal, survey.sizeTotal-survey.realTotal, survey.blocks*8L);
  385.     somPrintf("SIZE\tCOUNT\n");
  386.     for( int i=0; i<kSizeSurveySize; i++ )
  387.         somPrintf("%d\t%ld\n",i<<2,sizes[i]);
  388.     somPrintf("[bigger]\t%ld\n",sizes[kSizeSurveySize]);
  389.     
  390.     extern unsigned long gAllocCounter[100+1]; // MemoryHe.cpp
  391.     somPrintf("\nOf all allocations:\nSIZE\tCOUNT\n");
  392.     for( int i=0; i<100; i++ )
  393.         somPrintf("%d\t%ld\n",i<<2,gAllocCounter[i]);
  394.     somPrintf("[bigger]\t%ld\n",gAllocCounter[100]);
  395.  
  396. #endif
  397. }
  398.  
  399.  
  400. //------------------------------------------------------------------------------
  401. // MMWalkHeap
  402. //------------------------------------------------------------------------------
  403.  
  404. struct HeapWalkData {
  405.     MMBlockInfoProc proc;
  406.     void *refCon;
  407. };
  408.  
  409. static MMBoolean CallHeapWalkProc( void *blk, unsigned long size, MMBoolean isObject,
  410.                                  void *refCon )
  411. {
  412.     if( isObject )
  413.         MMValidateObject((SOMObject*)blk);
  414.     else
  415.         MMValidatePtr(blk,false);
  416.         
  417.     HeapWalkData *data = (HeapWalkData*) refCon;
  418.     return (data->proc) (blk, size, isObject, data->refCon);
  419. }
  420.  
  421.  
  422.  
  423. void
  424. MMWalkHeap( MemHeap *heapID, MMBlockInfoProc proc, void *refCon )
  425. {
  426.     MemoryHeap *heap = (MemoryHeap*)( heapID ?heapID :MMGetDefaultHeap() );
  427.     
  428.     HeapWalkData data;
  429.     data.proc = proc;
  430.     data.refCon = refCon;
  431.     heap->Check((HeapWalkProc)CallHeapWalkProc,&data);
  432. }
  433.  
  434. MMBoolean
  435. MMFindBlockContaining( const void *start, const void *end,
  436.                        const void* *blockStart, const void* *blockEnd )
  437. {
  438.     const void *foo, *bar;
  439.     if( !blockStart ) blockStart=&foo;
  440.     if( !blockEnd   ) blockEnd=&bar;
  441.         
  442.     if( end<start ) {
  443.         const void *temp = end;
  444.         end = start;
  445.         start = temp;
  446.     }
  447.  
  448.     MemoryHeap *heap = (MemoryHeap*)MMGetDefaultHeap();
  449.     return heap->FindBlockContaining(start,end,*blockStart,*blockEnd);
  450. }
  451.  
  452.  
  453. MMBoolean
  454. MMValidateMemoryRange( const void *start, const void *end )
  455. {
  456.     // Warn if memory range is in default heap but not entirely within a valid block:
  457.     if( end<start ) {
  458.         const void *temp = end;
  459.         end = start;
  460.         start = temp;
  461.     }
  462.     const void *blockStart, *blockEnd;
  463.     MemoryHeap *heap = (MemoryHeap*)MMGetDefaultHeap();
  464.     if( heap->FindBlockContaining(start,end, blockStart,blockEnd) )
  465.         if( blockStart==NULL ) {
  466.             MM_WARN("Mem range %p--%p is in heap but not in any block", start,end);
  467.             return kMMFalse;
  468.         } else if( start<blockStart || end>blockEnd ) {
  469.             MM_WARN("Mem range %p--%p violates block %p--%p",
  470.                     start,end, blockStart,blockEnd);
  471.             return kMMFalse;
  472.         }
  473.     return kMMTrue;
  474. }
  475.  
  476.  
  477. //========================================================================================
  478. // Block Stack Crawls
  479. //========================================================================================
  480.  
  481. MMBoolean
  482. MMTrackStackCrawls( MMBoolean track )
  483. {
  484.     MMBoolean old = CBlockStackCrawlHook::gTrack;
  485.     CBlockStackCrawlHook::gTrack = track;
  486.     return old;
  487. }
  488.  
  489.  
  490. StackCrawl*
  491. MMGetBlockStackCrawl( const void *block, long *flags )
  492. {
  493.     BestFitHeap *heap = GetHeap(block,"MMGetBlockStackCrawl");
  494.     if( heap ) {
  495.         size_t s = (size_t) heap->GetBlockStackCrawl(block);
  496.         if( flags ) *flags = s & 3;
  497.         return (StackCrawl*)( s & ~3L );
  498.     } else {
  499.         if( flags ) *flags = 0;
  500.         return NULL;
  501.     }
  502. }
  503.  
  504.  
  505. void
  506. MMSetBlockStackCrawl( const void *block, StackCrawl *s, long flags )
  507. {
  508.     BestFitHeap *heap = GetHeap(block,"MMSetBlockStackCrawl");
  509.     if( heap )
  510.         heap->SetBlockStackCrawl( block, (StackCrawl*)( (size_t)s | (flags & 3)) );
  511. }
  512.  
  513.  
  514. //========================================================================================
  515. // Memory Leak Detection
  516. //========================================================================================
  517.  
  518.  
  519. struct LeakLink {
  520.     LeakLink*        fNext;
  521.     const void*        fFirstBlock;
  522.     StackCrawl*        fStack;
  523.     unsigned long    fCount;
  524. };
  525.  
  526. static LeakLink *sLeakLinks;
  527.  
  528.  
  529. static MMBoolean InitLeaksProc(  const void *blk, size_t size, MMBoolean isObject,
  530.                                     void *refCon )
  531. {
  532.     // Nuke all previous stack crawls:
  533.     long flags;
  534.     StackCrawl *s = MMGetBlockStackCrawl(blk,&flags);
  535.     if( s ) {
  536.         delete s;
  537.         MMSetBlockStackCrawl(blk,NULL,0);
  538.     }
  539.     return kMMTrue;
  540. }
  541.  
  542.  
  543. void
  544. MMBeginLeakChecking( )
  545. {
  546.     somPrintf("••• Scanning for memory leaks: please do something 3 or more times.\r");
  547.     MMWalkHeap(NULL,(MMBlockInfoProc) &InitLeaksProc,NULL);
  548.     MMTrackStackCrawls(kMMTrue);
  549. }
  550.  
  551.  
  552. extern "C" {
  553. static MMBoolean FindLeaksProc(  const void *blk, size_t size, MMBoolean isObject,
  554.                                     void *refCon )
  555. {
  556.     long flags;
  557.     StackCrawl *s = MMGetBlockStackCrawl(blk,&flags);
  558.     if( s ) {
  559.         // This is a new block, check its stack crawl:
  560.         LeakLink *l;
  561.         for( l=sLeakLinks; l; l=l->fNext )
  562.             if( *(l->fStack) == *s ) {
  563.                 l->fCount++;
  564.                 delete s;
  565.                 MMSetBlockStackCrawl(blk,NULL,0);
  566.                 return kMMTrue;
  567.             }
  568.         l = new LeakLink;
  569.         l->fNext = sLeakLinks;
  570.         l->fFirstBlock = blk;
  571.         l->fStack = s;
  572.         l->fCount = 1;
  573.         sLeakLinks = l;
  574.     }
  575.     return kMMTrue;
  576. }
  577. }
  578.  
  579. static MMBoolean DumpObjProc(  const void *blk, size_t size, MMBoolean isObject,
  580.                                 void *dumpStack )
  581. {
  582.     if( isObject ) {
  583.         MMValidateObject((SOMObject*)blk);
  584.         somPrintf("  %p %4lu  %s\r", blk,size, ((SOMObject*)blk)->somGetClassName());
  585.     } else if( dumpStack )
  586.         somPrintf("  %p %4lu\r", blk,size);
  587.     if( dumpStack ) {
  588.         StackCrawl *s = MMGetBlockStackCrawl(blk,NULL);
  589.         if( s ) {
  590.             for( long i=0; i<s->CountFrames(); i++ ) {
  591.                 char name[256];
  592.                 s->GetFrameName(i,name);
  593.                 somPrintf("        %s\n",name);
  594.             }
  595.         }
  596.     }
  597.     return true;        // Might check for cmd-period or something to abort...
  598. }
  599.  
  600. void
  601. MMEndLeakChecking( )
  602. {
  603.     MMTrackStackCrawls(kMMFalse);
  604.     
  605.     somPrintf("••• Dumping memory leaks:\r");
  606.     sLeakLinks = NULL;
  607.     MMWalkHeap(NULL,&FindLeaksProc,NULL);
  608.     size_t leakage = 0;
  609.     LeakLink *next;
  610.     for( LeakLink *l=sLeakLinks; l; l=next ) {
  611.         next = l->fNext;
  612.         if( l->fCount >= 3 ) {
  613.             somPrintf("• Leaked %d times:\r", l->fCount);
  614.             size_t size = MMBlockSize(l->fFirstBlock);
  615.             DumpObjProc(l->fFirstBlock,
  616.                         size,
  617.                         MMIsObject(l->fFirstBlock),
  618.                         (void*)kMMTrue);
  619.             leakage += l->fCount * (size+8);    // Add 8 bytes for per-block overhead
  620.         }
  621.         delete l->fStack;
  622.         MMSetBlockStackCrawl(l->fFirstBlock,NULL,0);
  623.         delete l;
  624.     }
  625.     sLeakLinks = NULL;
  626.     if( leakage > 0 )
  627.         somPrintf("••• Estimated leakage: %ld bytes\r", leakage);
  628.     else
  629.         somPrintf("••• No leaks found!\r");
  630. }
  631.  
  632. //------------------------------------------------------------------------------
  633. // MMFillHeap
  634. //------------------------------------------------------------------------------
  635.  
  636. void MMFillHeap(MMBlockType whichAllocations)
  637. {
  638.     if (whichAllocations & kMMBlock)
  639.         gDefaultHeap->SetMemFullMark();
  640.     if (whichAllocations & kMMPlatformBlock)
  641.         MMSetPlatformBlockMemFullMark();
  642.     if (whichAllocations & kMMPlatformHandle)
  643.         MMSetPlatformHandleMemFullMark();
  644. }
  645.  
  646. //------------------------------------------------------------------------------
  647. // MMUnfillHeap
  648. //------------------------------------------------------------------------------
  649.  
  650. void MMUnfillHeap(MMBlockType whichAllocations)
  651. {
  652.     if (whichAllocations & kMMBlock)
  653.         gDefaultHeap->SetMemFullMark();
  654.     if (whichAllocations & kMMPlatformBlock)
  655.         MMUnsetPlatformBlockMemFullMark();
  656.     if (whichAllocations & kMMPlatformHandle)
  657.         MMUnsetPlatformHandleMemFullMark();
  658. }
  659.  
  660. //========================================================================================
  661. // Non-Debug Stubs
  662. //========================================================================================
  663.  
  664. #else /* MM_DEBUG */
  665.  
  666.  
  667. void        MMBeginMemValidation( ) { }
  668. void        MMEndMemValidation( ) { }
  669. void        MMBeginHeapChecking( ) { }
  670. void        MMEndHeapChecking( ) { }
  671.  
  672. MMBoolean    MMValidatePtr( ConstMMBlock, MMBoolean validateHeap, const char *operation )
  673.                                                     {return 1;}
  674. MMBoolean    MMValidateObject( const SOMObject *o ) {return 1;}
  675. MMBoolean    MMValidateHandle( MMHandle ) {return 1;}
  676.  
  677. MMBoolean    MMDoesHeapExist( MemHeap *heap ) {return 1;}
  678. MMBoolean    MMValidateHeap( MemHeap *heapID, const void* ptr ) {return 1;}
  679. MMBoolean    MMValidateAllHeaps( ) {return 1;}
  680.  
  681. void        MMGetHeapInfo( MemHeap *heapID,
  682.                             const char* *name, size_t *allocated, size_t *free,
  683.                             size_t *nBlocks, size_t *nObjects ) { }
  684.  
  685. void        MMWalkHeap( MemHeap *heapID, MMBlockInfoProc, void *StackCrawl )  { }
  686.  
  687. MMBoolean    MMFindBlockContaining( const void *, const void*,
  688.                                     const void* *blockStart, const void* *blockEnd )
  689. {
  690.     if( blockStart ) *blockStart=NULL;
  691.     return 0;
  692. }
  693. MMBoolean    MMValidateMemoryRange( const void *start, const void *end )    {return 1;}
  694.  
  695. MMBoolean    MMTrackStackCrawls( MMBoolean ) {return 0;}
  696. StackCrawl* MMGetBlockStackCrawl( const void *block, long *flags )
  697.     {if( flags ) *flags = 0; return NULL;}
  698. void MMSetBlockStackCrawl( const void *block, StackCrawl*, long flags ) { }
  699.  
  700. void        MMBeginLeakChecking( void )    { }
  701. void        MMEndLeakChecking( void ) { }
  702.  
  703. void        MMFillHeap(MMBlockType whichAllocations) {}
  704. void        MMUnfillHeap(MMBlockType whichAllocations) {}
  705.  
  706.  
  707. #endif /* MM_DEBUG */
  708.